﻿using System;
using System.Collections.Generic;

namespace DatabaseStuff
{
    public abstract class HashMap<TKey,TVal>
        :IReadOnlyDictionary<TKey,TVal>,
        ICollection<TVal>
    {
        private IDictionary<TKey, TVal> records;

        public HashMap()
        {
            records = new Dictionary<TKey, TVal>();
        }

        /// <summary>
        /// DI-compatible constructor. In order to ensure
        /// integrity of the records, the dictionary passed as a
        /// parameter to this constructor will be cleared during
        /// construction.
        /// </summary>
        internal HashMap(IDictionary<TKey, TVal> _records)
        {
            records = _records;
            records.Clear();
        }

        protected abstract TKey GetKeyFromValue(TVal value);

        protected IDictionary<TKey, TVal> Records
        {
            get { return records; }
        }

        public bool ContainsKey(TKey key)
        {
            return records.ContainsKey(key);
        }

        public IEnumerable<TKey> Keys
        {
            get { return records.Keys; }
        }

        public bool TryGetValue(TKey key, out TVal value)
        {
            return records.TryGetValue(key, out value);
        }

        public IEnumerable<TVal> Values
        {
            get { return records.Values; }
        }

        public TVal this[TKey key]
        {
            get { return records[key]; }
        }

        public int Count
        {
            get { return records.Count; }
        }

        public IEnumerator<KeyValuePair<TKey, TVal>> GetEnumerator()
        {
            return records.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return records.GetEnumerator();
        }

        public void Add(TVal item)
        {
            records.Add(GetKeyFromValue(item), item);
        }

        public void Clear()
        {
            records.Clear();
        }

        public bool Contains(TVal item)
        {
            return records.ContainsKey(GetKeyFromValue(item));
        }

        public void CopyTo(TVal[] array, int arrayIndex)
        {
            records.Values.CopyTo(array, arrayIndex);
        }

        public bool IsReadOnly
        {
            get { return records.IsReadOnly; }
        }

        public bool Remove(TVal item)
        {
            return records.Remove(GetKeyFromValue(item));
        }

        IEnumerator<TVal> IEnumerable<TVal>.GetEnumerator()
        {
            return records.Values.GetEnumerator();
        }
    }
}
